#ifndef YEP_UI_STYLE_BASE_HPP
#define YEP_UI_STYLE_BASE_HPP

#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include <string>
#include "ButtonStatus.hpp"
#include "../math/Vector2.hpp"
#include "../math/Rect.hpp"
#include "../video/Color.hpp"

namespace yep
{
    using namespace std;
    /**
     * @brief A _style made to be base to other styles.
     *
     * This class only have poor implementation to every method required by the Widgets.
     *  These methods are all virtual, so you can override to a more sophisticated version
     *  all @b necessary methods, and leave the default implementation for the other ones.
     *  (for instance, you can provide versions to the widgets you will actually use and avoid
     *  to do it for the ones you wouldn't use.)
     *
     *  @deprecated
     **/
    class StyleBaseOld
    {
    public:
        /**
         * @brief Draws the text on screen.
         *
         * It just is responsible to characters, ignoring the control codes (as tabs and new lines).
         *
         * @param screen The surface to draw the text;
         * @param text The text to be drawn;
         * @param position The absolute position to draw the text on screen;
         * @param rect The portion of the text to be draw.
         **/
        virtual void drawText( SDL_Surface* screen, const string& text, const Vector2& position, const Rect& rect, const Color& color )
        {
            Rect clipArea( position.x, position.y, rect.getW(), rect.getH() );
            SDL_SetClipRect( screen, clipArea );
            stringColor( screen, position.x - rect.getX(), position.y - rect.getY(), text.c_str(), color );
            SDL_SetClipRect( screen, NULL );
        }

        /**
         * @brief Discover the best size
         **/
        virtual void textArea( const string& text, Uint16& w, Uint16& h ) const
        {
            h = 8;
            w = text.size() * 8;
        }

        /**
         * @brief Return the dafalt colors
         *
         * By default is black and white, but can change in specializations.
         **/
        virtual void defaultColors( Color& textColor, Color& backgroundColor )
        {
            textColor = Color::BLACK;
            backgroundColor = Color::WHITE;
        }

        /**
         * @brief Returns a instance to the style.
         **/
        static StyleBaseOld& defaultStyle()
        {
            return _defaultStyle;
        }

        /**
         * @brief Draws the label.
         *
         * @param screen The surface to draw the text;
         * @param text The text to be drawn;
         * @param focused The focus status;
         * @param position The absolute position to draw the text on screen;
         * @param rect The portion of the text to be draw.
         **/
        virtual void drawLabel( SDL_Surface* screen, const string& text, bool focused, const Vector2& position, const Rect& rect,
                                const Color& textColor, const Color& backgroundColor )
        {
            drawText( screen, text, position, rect, textColor );
        }

        /**
         * @brief Discover the best size
         **/
        virtual void labelArea( const string& text, Uint16& w, Uint16& h ) const
        {
            textArea( text, w, h );
        }

        /**
         * @brief Draws the button.
         *
         * It depends internally the DrawText method, so be careful you overload it.
         *
         * @param screen The surface to draw the text;
         * @param status The status of the button;
         * @param text The text to be drawn;
         * @param position The absolute position to draw the text on screen;
         * @param rect The portion of the text to be draw.
         **/
        virtual void drawButton( SDL_Surface* screen, ButtonStatus status, const string& text, bool fucused, const Vector2& position,
                                 const Rect& rect, const Color& textColor, const Color& backgroundColor )
        {
            Rect clipArea( position.x, position.y, rect.getW(), rect.getH() );
            boxColor( screen, clipArea.x(), clipArea.y(), clipArea.getX2(), clipArea.getY2(), backgroundColor );
            --clipArea.w();
            --clipArea.h();
            ++clipArea.x();
            ++clipArea.y();
            rectangleColor( screen, clipArea.x(), clipArea.y(), clipArea.getX2(), clipArea.getY2(), status == PRESSED ? Color::BLACK : Color::WHITE );
            --clipArea.x();
            --clipArea.y();
            rectangleColor( screen, clipArea.x(), clipArea.y(), clipArea.getX2(), clipArea.getY2(), status == PRESSED ? Color::WHITE : Color::BLACK );

            if( status == PRESSED )
            {
                Rect adpt( rect.getX() - 2, rect.getY() - 3, rect.getW() - 2, rect.getH() - 1 );
                drawText( screen, text, position, adpt, textColor );
            }
            else
            {
                Rect adpt( rect.getX() - 2, rect.getY() - 2, rect.getW() - 2, rect.getH() - 2 );
                drawText( screen, text, position, adpt, textColor );
            }
        }

        /**
         * @brief Discover the best size
         **/
        virtual void buttonArea( const string& text, Uint16& w, Uint16& h ) const
        {
            textArea( text, w, h );
            w += 4;
            h += 4;
        }


        /**
         * @brief Draws the textInput.
         *
         * It depends internally the DrawText method, so be careful you overload it.
         *
         * @param screen The surface to draw the text;
         * @param text The text to be drawn;
         * @param focused If the widget is focused;
         * @param position The absolute position to draw the text on screen;
         * @param rect The portion of the text to be draw.
         **/
        virtual void drawTextInput( SDL_Surface* screen, const string& text, bool focused, const Vector2& position, const Rect& rect,
                                    const Color& textColor, const Color& backgroundColor )
        {
            int y = position.y + rect.getH() - 1;
            int xMin = position.x;
            int xMax = position.x + rect.getW();

            for( int x = xMin; x < xMax; x += 8 )
            {
                hlineColor( screen, x, x + 6, y, 0x000000FF );
            }

            int cursor = text.size() * 8;

            if( focused && position.x + rect.getW() > cursor + xMin )
                boxColor( screen, cursor + xMin, position.y, cursor + xMin + 6, y - 2, 0x000000FF );

            drawText( screen, text, position, rect, textColor );
        }

        /**
         * @brief Discover the best size
         **/
        virtual void textInputArea( const string& text, Uint16& w, Uint16& h ) const
        {
            h = 10;
            w = text.size() * 8;
        }

        /**
         * @brief Draws the window
         *
         * @param screen The surface to draw the text;
         * @param title The title of the window;
         * @param focused If the widget is focused;
         * @param position The absolute position to draw the text on screen;
         * @param rect The portion of the text to be draw.
         **/
        virtual void drawWindow( SDL_Surface* screen, const string& title, bool focused, bool tranparent, const Vector2 position,
                                 const Rect& rect, const Color& textColor, const Color& backgroundColor )
        {
            if( !tranparent )
            {
                Rect drawArea( position.x, position.y, rect.getW(), rect.getH() );
                rectangleColor( screen, drawArea.x(), drawArea.y(), drawArea.getX2(), drawArea.getY2(), backgroundColor );
                boxColor( screen, drawArea.x() + 2, drawArea.y() + 2, drawArea.getX2() - 2, drawArea.getY2() - 2, backgroundColor );
            }
        }

        /**
         * @brief setup window borders
         **/
        virtual void windowBorders( Uint8& leftBorder, Uint8& topBorder, Uint8& rightBorder, Uint8& bottomBorder )
        {
            leftBorder = topBorder = rightBorder = bottomBorder = 3;
        }

        /**
         * @brief Draws a checkbutton
         **/
        virtual void drawCheckButton( SDL_Surface* screen, ButtonStatus status, const string& text, bool fucused, bool checked,
                                      const Vector2& position, const Rect& rect, const Color& textColor, const Color& backgroundColor )
        {
            Rect box( position.x, position.y, 8, 8 );
            boxColor( screen, box.x() + 1, box.y() + 1, box.getX2() - 1, box.getY2() - 1, backgroundColor );
//            rectangleColor( screen, box.x(), box.y(), box.X2(), box.Y2(), textColor );
            hlineColor( screen, box.x() + 1, box.getX2() - 1, box.y(), textColor );
            hlineColor( screen, box.x() + 1, box.getX2() - 1, box.getY2(), textColor );
            vlineColor( screen, box.x(), box.y() + 1, box.getY2() - 1, textColor );
            vlineColor( screen, box.getX2(), box.y() + 1, box.getY2() - 1, textColor );

            if( checked )
            {
                lineColor( screen, box.x() + 1, box.y() + 1, box.getX2() - 1, box.getY2() - 1, textColor );
                lineColor( screen, box.x() + 1, box.getY2() - 1, box.getX2() - 1, box.y() + 1, textColor );
            }

            Rect absoluteRect( rect );
            absoluteRect.w() -= 8;
            Vector2 absolutePosition( position );
            absolutePosition.x += 8;
            drawText( screen, text, absolutePosition, absoluteRect, textColor );
        }

        /**
         * @brief Discover the best size
         **/
        virtual void checkButtonArea( const string& text, Uint16& w, Uint16& h ) const
        {
            textArea( text, w, h );
            w += 8;
        }

        /**
         * @brief Draws a checkbutton
         **/
        virtual void drawRadioButton( SDL_Surface* screen, ButtonStatus status, const string& text, bool fucused, bool checked,
                                      const Vector2& position, const Rect& rect, const Color& textColor, const Color& backgroundColor )
        {
            Rect box( position.x, position.y, 8, 8 );
            boxColor( screen, box.x() + 1, box.y() + 1, box.getX2() - 1, box.getY2() - 1, backgroundColor );
            hlineColor( screen, box.x() + 1, box.getX2() - 1, box.y(), textColor );
            hlineColor( screen, box.x() + 1, box.getX2() - 1, box.getY2(), textColor );
            vlineColor( screen, box.x(), box.y() + 1, box.getY2() - 1, textColor );
            vlineColor( screen, box.getX2(), box.y() + 1, box.getY2() - 1, textColor );

            if( checked )
            {
               boxColor( screen, box.x() + 2, box.y() + 2, box.getX2() - 2, box.getY2() - 2, textColor );
            }

            Rect absoluteRect( rect );
            absoluteRect.w() -= 8;
            Vector2 absolutePosition( position );
            absolutePosition.x += 8;
            drawText( screen, text, absolutePosition, absoluteRect, textColor );
        }

        /**
         * @brief Discover the best size
         **/
        virtual void radioButtonArea( const string& text, Uint16& w, Uint16& h ) const
        {
            textArea( text, w, h );
            w += 8;
        }
    private:
        static StyleBaseOld _defaultStyle;
    };
}

#endif // YEP_UI_STYLE_BASE_HPP

